package com.mia.craftstudio;

import com.mia.craftstudio.libgdx.Quaternion;
import com.mia.craftstudio.utils.ImageIOCS;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

public class CSModel {
   private final byte asset_type;
   private final short format_version;
   private final short next_unused_id;
   private final short node_count;
   private final Map nodes = new LinkedHashMap();
   private final Set topNodes = new HashSet();
   private final int texture_size;
   private final byte[] texture_data;
   private final short animation_count;
   private final short[] animation_asset_id;
   private static final String sep = ".";
   private BufferedImage texture;
   private boolean hasTransparency = false;
   private CSModel.ModelNode root;
   private final HashMap asset_ids_for_name = new HashMap();
   private final HashMap animation_conflict_blacklist = new HashMap();

   public CSModel(ByteBuffer buffer) throws CSExceptions.TypeMismatchException, CSExceptions.UnsupportedVersionException, IOException {
      this.asset_type = buffer.get();
      if (this.asset_type != 0) {
         throw new CSExceptions.TypeMismatchException((byte)0, this.asset_type);
      } else {
         this.format_version = buffer.getShort();
         if (this.format_version != 5) {
            throw new CSExceptions.UnsupportedVersionException(this.format_version);
         } else {
            this.next_unused_id = buffer.getShort();
            this.node_count = buffer.getShort();

            int i;
            CSModel.ModelNode node;
            for(i = 0; i < this.node_count; ++i) {
               node = new CSModel.ModelNode(this, buffer);
               this.nodes.put(node.getNodeID(), node);
            }

            Iterator var7 = this.nodes.values().iterator();

            while(var7.hasNext()) {
               node = (CSModel.ModelNode)var7.next();
               node.parseAttributes();
            }

            buffer.get(this.texture_data = new byte[this.texture_size = buffer.getInt()]);
            this.animation_count = buffer.getShort();
            this.animation_asset_id = new short[this.animation_count];

            for(i = 0; i < this.animation_count; ++i) {
               this.animation_asset_id[i] = buffer.getShort();
            }

            var7 = this.nodes.values().iterator();

            CSModel.ModelNode node2;
            while(var7.hasNext()) {
               node2 = (CSModel.ModelNode)var7.next();
               if (node2.getParentNodeID() == -1) {
                  if (this.root == null && node2.name.startsWith("RootNode")) {
                     this.root = node2;
                  }

                  this.topNodes.add(node2);
               } else {
                  node = (CSModel.ModelNode)this.nodes.get(node2.getParentNodeID());
                  node.addChild(node2);
                  node2.setParent(node);
               }
            }

            var7 = this.nodes.values().iterator();

            while(var7.hasNext()) {
               node2 = (CSModel.ModelNode)var7.next();
               node2.genFullName();
            }

            this.texture = ImageIOCS.read(new ByteArrayInputStream(this.texture_data));
            if (this.texture == null) {
               this.texture = CraftStudioLib.getDefaultTexture();
            }

            Raster alphaChannel = this.texture.getAlphaRaster();

            Iterator var9;
            for(var9 = this.nodes.values().iterator(); var9.hasNext(); this.hasTransparency = this.hasTransparency || node.hasAttribute(CSModel.ModelNode.Attrb.TRANSPARENT)) {
               node = (CSModel.ModelNode)var9.next();
               node.checkTransparency(alphaChannel);
            }

            for(var9 = this.nodes.values().iterator(); var9.hasNext(); ((ArrayList)this.asset_ids_for_name.get(node.getName())).add(node.getNodeID())) {
               node = (CSModel.ModelNode)var9.next();
               if (!this.asset_ids_for_name.containsKey(node.getName())) {
                  this.asset_ids_for_name.put(node.getName(), new ArrayList());
               }
            }

            if (this.animation_count > 0) {
               short[] var10 = this.animation_asset_id;
               int var11 = var10.length;

               for(int var5 = 0; var5 < var11; ++var5) {
                  short animID = var10[var5];
                  this.animation_conflict_blacklist.put(animID, new ArrayList());
               }
            }

         }
      }
   }

   public BufferedImage getTexture() {
      return this.texture;
   }

   public byte[] getRawTexture() {
      return this.texture_data;
   }

   public Collection getNodes() {
      return this.nodes.values();
   }

   public Collection getTopNodes() {
      return this.topNodes;
   }

   public short getAnimationCount() {
      return this.animation_count;
   }

   public short[] getAnimationAssetIDS() {
      return this.animation_asset_id;
   }

   public boolean hasTransparency() {
      return this.hasTransparency;
   }

   public CSModel.ModelNode getRootNode() {
      return this.root;
   }

   public void setupAnimationBlacklists(CSProject project) {
      if (this.animation_count >= 2) {
         for(short test_anim = 0; test_anim < this.animation_count; ++test_anim) {
            for(short target_anim = 0; target_anim < this.animation_count; ++target_anim) {
               Set dupes = project.getAnimation(Integer.valueOf(test_anim)).getModelNamesAffected();
               dupes.retainAll(project.getAnimation(Integer.valueOf(target_anim)).getModelNamesAffected());
               if (!dupes.isEmpty()) {
                  ((ArrayList)this.animation_conflict_blacklist.get(test_anim)).add(target_anim);
                  ((ArrayList)this.animation_conflict_blacklist.get(target_anim)).add(test_anim);
               }
            }
         }

      }
   }

   public static class ModelNode {
      private final short id;
      private final short parent_node_id;
      private final String name;
      private final float[] position = new float[3];
      private final float[] offset = new float[3];
      private final float[] scale = new float[3];
      private final Quaternion orientation;
      private final short[] size = new short[3];
      private final byte unwrap;
      private final CSModel.Point[] quads = new CSModel.Point[6];
      private final byte[] uvtransform = new byte[6];
      private final Set children = new HashSet();
      private CSModel.ModelNode parent = null;
      private final CSModel csmodel;
      private EnumSet attributes = EnumSet.noneOf(CSModel.ModelNode.Attrb.class);
      private boolean attributesParsed = false;
      private String fullName;

      public ModelNode(CSModel model, ByteBuffer buffer) {
         this.csmodel = model;
         this.id = buffer.getShort();
         this.parent_node_id = buffer.getShort();
         byte[] tmpName = new byte[buffer.get()];
         buffer.get(tmpName);
         this.name = new String(tmpName);
         this.fullName = this.getCleanName();

         int i;
         for(i = 0; i < 3; ++i) {
            this.position[i] = buffer.getFloat();
         }

         for(i = 0; i < 3; ++i) {
            this.offset[i] = buffer.getFloat();
         }

         for(i = 0; i < 3; ++i) {
            this.scale[i] = buffer.getFloat();
         }

         this.orientation = new Quaternion(buffer);

         for(i = 0; i < 3; ++i) {
            this.size[i] = buffer.getShort();
         }

         this.unwrap = buffer.get();

         for(i = 0; i < 6; ++i) {
            this.quads[i] = new CSModel.Point(buffer);
         }

         for(i = 0; i < 6; ++i) {
            this.uvtransform[i] = buffer.get();
         }

      }

      private void parseAttributes() {
         if (!this.attributesParsed) {
            String s = this.name.contains("$") ? this.name.split("\\$")[1] : "";
            CSModel.ModelNode.Attrb[] var2 = CSModel.ModelNode.Attrb.values();
            int var3 = var2.length;

            for(int var4 = 0; var4 < var3; ++var4) {
               CSModel.ModelNode.Attrb a = var2[var4];
               boolean addAttrib = false;
               if (a.hasAttribute(s)) {
                  addAttrib = true;
               } else if (a.propagates() && this.parent_node_id != -1) {
                  CSModel.ModelNode parentNode = (CSModel.ModelNode)this.csmodel.nodes.get(this.parent_node_id);
                  parentNode.parseAttributes();
                  addAttrib = parentNode.hasAttribute(a);
               }

               if (addAttrib) {
                  this.attributes.add(a);
               }
            }

            this.attributesParsed = true;
         }
      }

      public boolean hasAttribute(CSModel.ModelNode.Attrb a) {
         return this.attributes.contains(a);
      }

      public CSModel.Point getTextureOffset() {
         int x = Integer.MAX_VALUE;
         int y = Integer.MAX_VALUE;

         for(int i = 0; i < 6; ++i) {
            x = Math.min(x, this.quads[i].x);
            y = Math.min(y, this.quads[i].y);
         }

         return new CSModel.Point(x, y);
      }

      public String getName() {
         return this.name;
      }

      public String getCleanName() {
         return this.name.split("\\$")[0];
      }

      public String getFullName() {
         return this.fullName;
      }

      public void genFullName() {
         this.fullName = this.getCleanName();

         for(CSModel.ModelNode currNode = this; currNode.getParent() != null; this.fullName = currNode.getCleanName() + "." + this.fullName) {
            currNode = currNode.getParent();
         }

      }

      public short[] getSize() {
         return this.size;
      }

      public float[] getSize(float scale) {
         return new float[]{(float)this.size[0] * scale, (float)this.size[1] * scale, (float)this.size[2] * scale};
      }

      public float[] getPosition() {
         return this.position;
      }

      public Quaternion getOrientation() {
         return this.orientation.cpy();
      }

      public short getParentNodeID() {
         return this.parent_node_id;
      }

      public short getNodeID() {
         return this.id;
      }

      public float[] getOffset() {
         return this.offset;
      }

      public float[] getScale() {
         return this.scale;
      }

      public Set getChildren() {
         return this.children;
      }

      public CSModel.ModelNode getParent() {
         return this.parent;
      }

      public void addChild(CSModel.ModelNode child) {
         this.children.add(child);
      }

      public void setParent(CSModel.ModelNode parent) {
         this.parent = parent;
      }

      public CSModel getModel() {
         return this.csmodel;
      }

      public BufferedImage getTexture() {
         return this.csmodel.getTexture();
      }

      public CSModel.Point[] getQuads() {
         return this.quads;
      }

      public boolean isNull() {
         return this.size[0] == 0 && this.size[1] == 0 && this.size[2] == 0;
      }

      public byte[] getUVTransform() {
         return this.uvtransform;
      }

      public boolean checkTransparency(Raster alphaChannel) {
         if (alphaChannel == null) {
            return false;
         } else {
            int[][] values = new int[6][];

            try {
               values[0] = alphaChannel.getPixels(this.quads[0].x, this.quads[0].y, this.size[0], this.size[1], (int[])null);
               values[1] = alphaChannel.getPixels(this.quads[1].x, this.quads[1].y, this.size[0], this.size[1], (int[])null);
               values[2] = alphaChannel.getPixels(this.quads[2].x, this.quads[2].y, this.size[0], this.size[1], (int[])null);
               values[3] = alphaChannel.getPixels(this.quads[3].x, this.quads[3].y, this.size[0], this.size[2], (int[])null);
               values[4] = alphaChannel.getPixels(this.quads[4].x, this.quads[4].y, this.size[2], this.size[1], (int[])null);
               values[5] = alphaChannel.getPixels(this.quads[5].x, this.quads[5].y, this.size[0], this.size[2], (int[])null);
               int[][] var3 = values;
               int var4 = values.length;

               for(int var5 = 0; var5 < var4; ++var5) {
                  int[] pixels = var3[var5];
                  int[] var7 = pixels;
                  int var8 = pixels.length;

                  for(int var9 = 0; var9 < var8; ++var9) {
                     int i = var7[var9];
                     if (i != 0 && i != 255) {
                        this.attributes.add(CSModel.ModelNode.Attrb.TRANSPARENT);
                        return true;
                     }
                  }
               }
            } catch (ArrayIndexOutOfBoundsException var11) {
            }

            return false;
         }
      }

      public String toString() {
         return String.format("CSMODEL %s | Position : [%.2f %.2f %.2f] | Size : [%d %d %d]", this.name, this.position[0], this.position[1], this.position[2], this.size[0], this.size[1], this.size[2]);
      }

      public static enum Attrb {
         PASSABLE("p"),
         PASSABLEPROPAGATES("P", true),
         TRANSPARENT("2"),
         IGNOREBELOWYPLANE("y"),
         COLORPRIMARY("C"),
         COLORSECONDARY("c"),
         COLORACCENTPRIMARY("A"),
         COLORACCENTSECONDARY("a"),
         AMBIENTOCCLUSION("o");

         private final String controlChar;
         private final boolean propagates;

         private Attrb(String controlChar) {
            this.controlChar = controlChar;
            this.propagates = false;
         }

         private Attrb(String controlChar, boolean propagates) {
            this.controlChar = controlChar;
            this.propagates = propagates;
         }

         public boolean hasAttribute(String s) {
            return s.contains(this.controlChar);
         }

         public final boolean propagates() {
            return this.propagates;
         }
      }
   }

   public static class Point {
      public final int x;
      public final int y;

      public Point(ByteBuffer buffer) {
         this.x = buffer.getInt();
         this.y = buffer.getInt();
      }

      public Point(int x, int y) {
         this.x = x;
         this.y = y;
      }
   }
}
